#include "preHeader.h"
#include "Guild.h"
#include "GuildMgr.h"
#include "Session/GameServerMgr.h"

Guild::Guild()
: m_guildMaster(0)
, m_totalFightValue(0)
, m_lastFightValueTime(0)
{
}

Guild::~Guild()
{
}

bool Guild::OnLoadDataFromDBFinished()
{
	for (auto&[playerId, guildMember] : m_guildMembers) {
		if (guildMember.guildTitle == (s8)GUILD_TITLE::MASTER) {
			m_guildMaster = guildMember.playerId;
			break;
		}
	}
	return true;
}

void Guild::SetGuildInfo(GuildInformation&& guildInfo)
{
	m_guildInfo = std::move(guildInfo);
}

void Guild::AddGuildMember(GuildMember&& guildMember)
{
	m_guildMembers.emplace(guildMember.playerId, std::move(guildMember));
	NewGuildMemberFightValue2Rank(guildMember.playerId);
}

void Guild::AddGuildApply(GuildApply&& guildApply)
{
	m_guildApplys.emplace(guildApply.playerId, std::move(guildApply));
}

void Guild::AddGuildInvite(GuildInvite&& guildInvite)
{
	m_guildInvites.emplace(guildInvite.targetId, std::move(guildInvite));
}

void Guild::RemoveGuildMember(uint32 playerId)
{
	m_guildMembers.erase(playerId);
	RemoveGuildMemberFightValue2Rank(playerId);
}

void Guild::RemoveGuildApply(uint32 playerId)
{
	m_guildApplys.erase(playerId);
}

void Guild::RemoveGuildInvite(uint32 playerId, bool isExpire)
{
	auto itr = m_guildInvites.find(playerId);
	if (itr != m_guildInvites.end()) {
		if (!isExpire) {
			sGuildMgr.RemoveTimers(itr->second.timer);
		}
		m_guildInvites.erase(itr);
	}
}

GuildMember* Guild::GetGuildMember(uint32 playerId)
{
	auto itr = m_guildMembers.find(playerId);
	return itr != m_guildMembers.end() ? &itr->second : NULL;
}

const GuildApply* Guild::GetGuildApply(uint32 playerId) const
{
	auto itr = m_guildApplys.find(playerId);
	return itr != m_guildApplys.end() ? &itr->second : NULL;
}

const GuildInvite* Guild::GetGuildInvite(uint32 playerId) const
{
	auto itr = m_guildInvites.find(playerId);
	return itr != m_guildInvites.end() ? &itr->second : NULL;
}

bool Guild::IsGuildMemberFull() const
{
	return m_guildMembers.size() >= 30;
}

void Guild::PullGuildMemberFightValue2Rank(uint32 playerId)
{
	NetPacket rpcReqPck(SGX_PULL_CHARACTER_INFOS);
	rpcReqPck << (u32)PullValueFlag::NonDict
		<< (u32)CharValueType::FightValue << playerId;
	sGameServerMgr.RPCInvoke2GS(rpcReqPck,
		[=, guildId = m_guildInfo.Id](INetStream& pck, int32 err, bool) {
		if (err == DBPErrorNone && !pck.IsReadableEmpty()) {
			if (sGuildMgr.GetGuild(guildId) && GetGuildMember(playerId)) {
				pck >> m_guildFightValues[playerId];
				PullTotalFightValue2Rank();
			}
		}
	}, &sGuildMgr, DEF_S2S_RPC_TIMEOUT);
}

void Guild::PullAllGuildMemberFightValues2Rank()
{
	NetPacket rpcReqPck(SGX_PULL_CHARACTER_INFOS);
	rpcReqPck << (u32)PullValueFlag::NonDict
		<< ((u32)CharValueType::Key | (u32)CharValueType::FightValue);
	for (auto& [playerId, guildMember] : m_guildMembers) {
		rpcReqPck << playerId;
	}
	sGameServerMgr.RPCInvoke2GS(rpcReqPck,
		[=, guildId = m_guildInfo.Id](INetStream& pck, int32 err, bool) {
		if (err != DBPErrorNone) {
			return;
		}
		if (sGuildMgr.GetGuild(guildId) == NULL) {
			return;
		}
		while (!pck.IsReadableEmpty()) {
			auto playerId = pck.Read<uint32>();
			if (GetGuildMember(playerId) != NULL) {
				pck >> m_guildFightValues[playerId];
			}
		}
		PullTotalFightValue2Rank();
	}, &sGuildMgr, DEF_S2S_RPC_TIMEOUT);
}

void Guild::NewGuildMemberFightValue2Rank(uint32 playerId)
{
	PullGuildMemberFightValue2Rank(playerId);
}

void Guild::RemoveGuildMemberFightValue2Rank(uint32 playerId)
{
	m_guildFightValues.erase(playerId);
	PullTotalFightValue2Rank();
}

void Guild::PullTotalFightValue2Rank()
{
	m_totalFightValue = 0;
	for (auto& [playerId, fightValue] : m_guildFightValues) {
		m_totalFightValue += fightValue;
	}
	sGuildMgr.UpdateGuildRankData(
		this, (int)RANK_SUBTYPE::GUILD_FIGHT_VALUE);
}
